package com.zjb.demo.system.service;

import com.zjb.demo.common.config.AppConfig;
import com.zjb.demo.common.constant.CacheConstants;
import com.zjb.demo.common.constant.Constants;
import com.zjb.demo.common.constant.ExceptionCode;
import com.zjb.demo.common.constant.SecurityConstants;
import com.zjb.demo.common.domain.LoginUser;
import com.zjb.demo.common.exception.AppException;
import com.zjb.demo.common.exception.ServiceException;
import com.zjb.demo.common.util.RSAUtils;
import com.zjb.demo.common.util.SecurityUtils;
import com.zjb.demo.framework.manager.AsyncManager;
import com.zjb.demo.system.domain.User;
import com.zjb.demo.system.domain.query.LoginBody;
import com.zjb.demo.system.domain.vo.TokenView;
import org.noear.redisx.plus.RedisBucket;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;

/**
 * @author 庄佳彬
 * @since 2023/12/28 17:46
 */
@Component
public class SysLoginService {

    @Inject
    private AppConfig appConfig;
    @Inject
    private RedisBucket redisBucket;

    @Inject
    private AsyncManager asyncManager;
    @Inject
    private UserService userService;

    @Inject
    private SysPermissionService permissionService;
    @Inject
    private TokenService tokenService;

    public TokenView login(LoginBody loginBody) {
        var password = RSAUtils.decrypt(loginBody.getPassword(), SecurityConstants.PRIVATE_KEY);
//        var password = loginBody.getPassword();
        var captchaEnabled = appConfig.getCaptchaEnabled();
        if (captchaEnabled) {
            validateCaptcha(loginBody.getUsername(), loginBody.getCode(), loginBody.getUuid());
        }
        var user = userService.getByUsername(loginBody.getUsername());
        var matches = user.map(User::getPassword)
                .map(pd -> SecurityUtils.matchesPassword(password, pd))
                .orElse(Boolean.FALSE);
        if (matches) {
            asyncManager.saveLoginInfo(loginBody.getUsername(), Constants.SUCCESS, "登录成功");
            return user
                    .map(u -> {
                        var id = u.getId();
                        userService.recordLoginInfo(id);
                        return new LoginUser(u.getId(), u.getDeptId(), u, permissionService.getMenuPermission(u));
                    })
                    .map(lu ->
                            tokenService.createToken(lu, loginBody.getMobileLogin())
                    )
                    .orElseThrow(() -> new ServiceException("错误"));
        } else {
            throw new AppException(ExceptionCode.INVALID_USERNAME_PASSWORD, "用户名或密码错误");
        }
    }

    private void validateCaptcha(String username, String code, String uuid) {
        var verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
        var captcha = redisBucket.get(verifyKey);
        redisBucket.remove(verifyKey);
        if (captcha == null) {
            asyncManager.saveLoginInfo(username, Constants.ERROR, "验证码过期！");
            throw new AppException(ExceptionCode.CAPTCHA_ERROR, "验证码过期");
        }
        if (!captcha.equalsIgnoreCase(code)) {
            asyncManager.saveLoginInfo(username, Constants.ERROR, "验证码错误！");
            throw new AppException(ExceptionCode.CAPTCHA_ERROR, "验证码错误");

        }
    }
}
